﻿namespace Blaze.Editor.UI
{
    using System;
    using System.Linq;
    using UnityEditor;
    using UnityEngine;
    using UnityEngine.Rendering;

    /// <summary>
    /// 用于显示Blaze的标准UI材质面板。
    /// </summary>
    public class StandardShaderGUI : ShaderGUI
    {
        public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties)
        {
            initializeGUIStyles();

            var material = (Material) materialEditor.target;
            materialEditor.SetDefaultGUIWidths();

            drawTextureProperty("_MainTex", materialEditor, properties);

            var enableAlphaSplitting = drawBooleanProperty(material, mKeywordAlphaSplit, "启用Alpha分离？");

            if (enableAlphaSplitting)
            {
                drawBooleanProperty(material, mKeywordAlphaSplitAutoETC1, "Alpha通道取r/a?");
                drawTextureProperty("_AlphaTex", materialEditor, properties);
            }
            

            var lastEnableHSBC = material.IsKeywordEnabled(mKeywordHSBC);
            var enableHSBC = drawBooleanProperty(material, mKeywordHSBC, "启用调色？");
            if (lastEnableHSBC != enableHSBC)
            {
                if (enableHSBC)
                    material.SetColor("_Color", new Color(0f, 0.5f, 0.5f, 0.5f));
                else
                    material.SetColor("_Color", Color.white);
            }
            if (enableHSBC)
            {
                var hsbc = material.GetColor("_Color");
                EditorGUI.BeginChangeCheck();
                drawHue(ref hsbc);
                drawSaturation(ref hsbc);
                drawBrightness(ref hsbc);
                drawConstract(ref hsbc);
                if (EditorGUI.EndChangeCheck())
                    material.SetColor("_Color", hsbc);
            }
            drawBlendMode(material);
        }

        private static bool drawBooleanProperty(Material material, string keyword, string displayName)
        {
            var isEnabled = Array.IndexOf(material.shaderKeywords, keyword) >= 0;
            EditorGUI.BeginChangeCheck();

            isEnabled = EditorGUILayout.Toggle(displayName, isEnabled);
            if (EditorGUI.EndChangeCheck())
            {
                if (isEnabled)
                    material.EnableKeyword(keyword);
                else
                    material.DisableKeyword(keyword);
            }
            return isEnabled;
        }

        private static void drawTextureProperty(string propertyName, MaterialEditor materialEditor, MaterialProperty[] properties)
        {
            var property = properties.First(p => p.name == propertyName);
            var rect = EditorGUILayout.GetControlRect(true, materialEditor.GetPropertyHeight(property, property.displayName), EditorStyles.layerMaskField);
            materialEditor.ShaderProperty(rect, property, property.displayName);
        }

        private CustomBlendMode drawBlendMode(Material material)
        {
            if (mBlendModeDrawer == null)
            {
                var srcBlendMode = (BlendMode) (int) material.GetFloat("_SrcBlend");
                var destBlendMode = (BlendMode) (int) material.GetFloat("_DstBlend");
                var blendOp = (BlendOp) (int) material.GetFloat("_BlendOp");
                mBlendModeDrawer = new CustomBlendModeDrawer("混合模式");
                mBlendModeDrawer.Select(blendOp, srcBlendMode, destBlendMode);
            }

            EditorGUI.BeginChangeCheck();
            var result = mBlendModeDrawer.Draw();
            if (EditorGUI.EndChangeCheck())
            {
                material.SetFloat("_BlendOp", (int) result.Op);
                material.SetFloat("_SrcBlend", (int) result.Src);
                material.SetFloat("_DstBlend", (int) result.Dest);
            }
            return result;
        }

        private CustomBlendModeDrawer mBlendModeDrawer;

        #region HSBC

        private static void drawHue(ref Color hsbc)
        {
            GUILayout.Label("色相 (Hue)");
            var input = (int) (hsbc.r*360);
            var hue = EditorGUILayout.Slider(input, 0, 360);
            var output = hue/360f;
            hsbc = new Color(output, hsbc.g, hsbc.b, hsbc.a);
        }

        private static void drawSaturation(ref Color hsbc)
        {
            GUILayout.Label("饱和度 (Saturation)");
            var saturation = EditorGUILayout.Slider(hsbc.g, 0, 1);
            hsbc = new Color(hsbc.r, saturation, hsbc.b, hsbc.a);
        }

        private static void drawBrightness(ref Color hsbc)
        {
            GUILayout.Label("明度 (Brightness)");
            var brightness = EditorGUILayout.Slider(hsbc.b, 0, 1);
            hsbc = new Color(hsbc.r, hsbc.g, brightness, hsbc.a);
        }

        private static void drawConstract(ref Color hsbc)
        {
            GUILayout.Label("对比度 (Constract)");
            var constract = EditorGUILayout.Slider(hsbc.a, 0, 1);
            hsbc = new Color(hsbc.r, hsbc.g, hsbc.b, constract);
        }

        #endregion

        #region GUIStyles

        private static void initializeGUIStyles()
        {
            if (mIsGUIStyleInitialized)
                return;
            mIsGUIStyleInitialized = true;
        }

        private static bool mIsGUIStyleInitialized;

        #endregion

        #region Keywords

        private const string mKeywordAlphaSplit = "BLAZE_UI_ALPHASPLIT";
        private const string mKeywordAlphaSplitAutoETC1 = "BLAZE_UI_ETC1COMPRESS";
        private const string mKeywordHSBC = "BLAZE_UI_HSBC";

        #endregion
    }
}